class Game {
  constructor(images, callback) {
    this.images = images;
    this.callback = callback;
    this.canvas = document.querySelector("canvas");
    this.context = this.canvas.getContext("2d");
    this.width = this.canvas.width;
    this.height = this.canvas.height;
    this.scene = null;
    this.actions = {};
    this.keydowns = {};
    window.addEventListener("keydown", (event) => {
      this.keydowns[event.key] = true;
    });
    window.addEventListener("keyup", (event) => {
      this.keydowns[event.key] = false;
    });
    this.init();
    // 这个挂在全局的哦
    window.game = this;
  }

  // 下面的代码是使用 promise.all 的方式实现的
  // https://q.shanyue.tech/roadmap/code#promiseall-%EF%B8%8F%EF%B8%8F%EF%B8%8F%EF%B8%8F%EF%B8%8F
  //   init() {
  //     let length = Object.keys(this.images).length;
  //     let loaded = [];
  //     for (let [name, path] of Object.entries(this.images)) {
  //       let img = new Image();
  //       img.src = path;
  //       img.onload = () => {
  //         this.images[name] = img;
  //         loaded.push(1);
  //         if (loaded.length === length) {
  //           this.callback();
  //         }
  //       };
  //     }
  //   }

  init() {
    let promises = this.loadImages();
    Promise.all(promises).then(() => {
      this.callback();
    });
  }

  loadImages() {
    let promises = [];

    for (let [name, path] of Object.entries(this.images)) {
      let img = new Image();
      img.src = path;

      let promise = new Promise((resolve) => {
        img.onload = () => {
          this.images[name] = img;
          resolve();
        };
      });

      promises.push(promise);
    }

    return promises;
  }

  update() {
    if (window.pause) {
      return;
    }
    this.scene.update();
  }

  clear() {
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
  }

  draw() {
    this.scene.draw();
  }

  runloop() {
    for (let [key, callback] of Object.entries(this.actions)) {
      if (this.keydowns[key]) {
        callback();
      }
    }
    this.update();
    this.clear();
    this.draw();
    setTimeout(() => {
      this.runloop();
    }, 1000 / config?.fps?.value ?? 60);
  }

  imageByName(name) {
    let image = this.images[name];
    return image;
  }

  runWithScene(scene) {
    this.scene = scene;
    setTimeout(() => {
      this.runloop();
    }, 1000 / (config?.fps?.value ?? 60));
  }

  replaceScene(scene) {
    this.scene = scene;
  }

  registerAction(key, callback) {
    this.actions[key] = callback;
  }
}
